package cn.hdu.liang.ch6;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Exchanger;

public class ExchangerDemo {
    final static Exchanger<DataBuffer> exchanger = new Exchanger<>();
    final static DataBuffer initialEmptyBuffer = new DataBuffer();
    final static DataBuffer initialFullBuffer = new DataBuffer("I");

    public static void main(String[] args) {

        class FillingLoop implements Runnable {
            int count = 0;

            @Override
            public void run() {
                DataBuffer currentBuffer = initialEmptyBuffer;
                try {
                    while(true) {
                        Thread.sleep(500);
                        addToBuffer(currentBuffer);
                        if(currentBuffer.isFull()) {
                            System.out.println("filling 线程正要 exchange");
                            currentBuffer = exchanger.exchange(currentBuffer);
                            System.out.println("filling 线程 exchange　完成");
                        }
                    }
                } catch(InterruptedException ie) {
                    System.out.println("filling 线程中断");
                }
            }

            void addToBuffer(DataBuffer buffer) {
                String item = "NI" + count++;
                System.out.println("Adding: " + item);
                buffer.add(item);
            }
        }

        class EmptyingLoop implements Runnable {
            @Override
            public void run() {
                DataBuffer currentBuffer = initialFullBuffer;
                try {
                    while(true) {
                        Thread.sleep(500);
                        takeFromBuffer(currentBuffer);
                        if(currentBuffer.isEmpty()) {
                            System.out.println("emptying 线程正要 exchange");
                            currentBuffer = exchanger.exchange(currentBuffer);
                            System.out.println("emptying 线程 exchange　完成");
                        }
                    }
                } catch(InterruptedException ie) {
                    System.out.println("emptying 线程中断");
                }
            }

            void takeFromBuffer(DataBuffer buffer) {
                System.out.println("taking: " + buffer.remove());
            }
        }

        new Thread(new EmptyingLoop()).start();
        new Thread(new FillingLoop()).start();
    }

}


class DataBuffer {
    private final static int MAXITEMS = 3;
    private final List<String> items = new ArrayList<>();

    public DataBuffer() {
    }

    public DataBuffer(String prefix) {
        for(int i = 0; i < MAXITEMS; i++) {
            String item = prefix + i;
            System.out.printf("Adding %s \n", item);
            items.add(item);
        }
    }

    synchronized void add(String s) {
        if(!isFull()) {
            items.add(s);
        }
    }

    synchronized boolean isFull() {
        return items.size() == MAXITEMS;
    }

    synchronized String remove() {
        if(!isEmpty()) {
            return items.remove(0);
        }
        return null;
    }

    synchronized boolean isEmpty() {
        return items.size() == 0;
    }

}
